package ffte.core.streamed

import spinal.core._
import spinal.lib._

import ffte.types.VecComplex
import ffte.property.{getFFTIW,getFFTOW,FFTIOConfig}
import ffte.algorithm.FFTGen.{msbFFT}

/**
 * Streamed Mixed-Space Block (MSB) FFT implementation
 *
 * This class implements FFT using the Mixed-Space Block decomposition method
 * with fully streamed architecture. The streamed MSB processes data through
 * a pipeline with twiddle factor multiplication and flow control.
 *
 * Mathematical Foundation:
 * The MSB method implements the Cooley-Tukey decomposition which breaks
 * an N-point DFT into smaller DFTs by reorganizing the computation into a
 * multi-dimensional structure. For N = N1 * N2:
 *
 * X[k1 + N1*k2] = Σ[n2=0 to N2-1] [ W_N^(k2*n2) * Σ[n1=0 to N1-1] ( x[n1 + N1*n2] * W_N1^(k1*n1) ) ] * W_N2^(k2*n1)
 *
 * Streamed MSB Architecture:
 * - First stage: N2 independent N1-point streamed FFTs
 * - Twiddle rotator: Complex multiplication with W_N factors
 * - Interleaver: Data reordering based on Cooley-Tukey mapping
 * - Second stage: N1 independent N2-point streamed FFTs
 *
 * Performance Characteristics:
 * - Works for any composite transform size
 * - High throughput through pipelined processing
 * - Requires N complex multiplications for twiddle factors
 * - Regular data access patterns with stride addressing
 *
 * @tparam T Streamed method type parameter
 * @param S Scaling shift amount for fixed-point overflow prevention
 * @param p MSB decomposition structure containing stage and twiddle information
 */
class msb[T <: Streamed](val S: Int, val p: msbFFT[T]) extends combineStreamedComponents[T] {
    /**
     * Second stage processing block
     *
     * This block implements the second stage of the MSB decomposition,
     * consisting of N1 independent N2-point streamed FFTs operating
     * in parallel. Each FFT processes the twiddle-rotated and reordered
     * intermediate data.
     *
     * Architecture:
     * - N1 parallel streamed FFT processors of size N2
     * - Input width: interW (intermediate precision)
     * - Output width: oW (global output precision)
     * - Streaming interface with flow control
     */
    val s_block = FFTIOConfig(interW, oW) on new Area {
        /**
         * Second stage streamed FFT processors
         *
         * Creates N1 independent streamed FFT processors using the
         * Streamed method with second stage scaling.
         */
        val u = sg(second, "s")
        val delay = u.delay
    }

    /**
     * Streamed twiddle factor rotator
     *
     * Implements complex multiplication with twiddle factors required
     * by the Cooley-Tukey decomposition. The rotator handles the
     * W_N^(k2*n1) terms that appear between the two FFT stages in
     * the streaming domain.
     *
     * Function:
     * - Generates twiddle factors based on permutation tables
     * - Performs complex multiplication with optimal precision
     * - Maintains streaming semantics and flow control
     */
    val r = rotator(interW, p.p.first.store_tab, p.p.second.load_tab)

    /**
     * Streamed interleaver for data reordering
     *
     * Implements the Cooley-Tukey data reordering required between
     * twiddle rotation and the second stage FFT. This interleaver
     * handles the complex index mapping in the streaming domain.
     *
     * Function:
     * - Routes data from rotator outputs to second stage inputs
     * - Implements Cooley-Tukey index permutation
     * - Maintains streaming semantics and flow control
     */
    val interleave = SInterleaver(interW, first.N, second.N)

    /**
     * Pipeline connections
     *
     * Data flows through the MSB pipeline:
     * 1. First stage FFT (f_block)
     * 2. Twiddle factor rotator (r)
     * 3. Data interleaver
     * 4. Second stage FFT (s_block)
     */
    f_block.u.io.q >> r.io.d              // First stage to rotator
    r.io.q >> interleave.io.d             // Rotator to interleaver
    interleave.io.q >> s_block.u.io.d    // Interleaver to second stage

    /**
     * External I/O connections
     *
     * Input data flows to the first stage and output data comes
     * from the second stage of the pipeline.
     */
    io.d >> f_block.u.io.d                // Input to first stage
    io.q << s_block.u.io.q                // Output from second stage

    /**
     * Total pipeline delay in clock cycles
     *
     * Total delay includes:
     * - First stage FFT delay (f_block.delay)
     * - Twiddle rotator delay (r.delay)
     * - Interleaver delay for data reordering (interleave.delay)
     * - Second stage FFT delay (s_block.delay)
     *
     * @return Total delay from input to output in clock cycles
     */
    def delay = f_block.delay + interleave.delay + s_block.delay + r.delay
}